﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Steve
{
    public static class DirectoryNodeExtensions
    {
        private static DirectoryNode<T, TMetadata>.NavigationResult NavigateToCore<T, TMetadata>(DirectoryNode<T, TMetadata> node, Uri url) 
            where T : class 
            where TMetadata : IDirectoryNodeMetadata
        {
            var path = GetPath(url).Substring(1);
            var query = !string.IsNullOrWhiteSpace(url.Query) ? url.Query.Substring(1) : null;

            return node.NavigateToCore(path, query);
        }

        public static Lazy<T, TMetadata> NavigateToItem<T, TMetadata>(this DirectoryNode<T, TMetadata> node, Uri url) 
            where T : class
            where TMetadata : IDirectoryNodeMetadata
        {
            if (url == null) throw new ArgumentNullException("url");

            var result = NavigateToCore(node, url);

            if (result.ExactMatch) return result.ItemMatch;

            return null;
        }

        public static DirectoryNode<T, TMetadata> NavigateToDirectory<T, TMetadata>(this DirectoryNode<T, TMetadata> node, Uri url)
            where T : class
            where TMetadata : IDirectoryNodeMetadata
        {
            if (url == null) throw new ArgumentNullException("url");

            var result = NavigateToCore(node, url);

            if (result.ExactMatch) return result.DirectoryMatch;

            return null;
        }

        public static DirectoryNode<T, TMetadata>.NavigationResult NavigateTo<T, TMetadata>(this DirectoryNode<T, TMetadata> node, string pathAndQuery)
            where T : class
            where TMetadata : IDirectoryNodeMetadata
        {
            if (node == null) throw new ArgumentNullException("node");
            if (string.IsNullOrWhiteSpace(pathAndQuery)) throw new ArgumentNullException("pathAndQuery");

            var parts = pathAndQuery.Split(new char[] { '?' }, 2, StringSplitOptions.None);

            var path = parts[0];
            string query = null;

            if (parts.Length > 1) query = parts[1];

            return node.NavigateToCore(path, query);
        }

        public static Lazy<T, TMetadata> NavigateToItem<T, TMetadata>(this DirectoryNode<T, TMetadata> node, string pathAndQuery)
            where T : class
            where TMetadata : IDirectoryNodeMetadata
        {
            if (node == null) throw new ArgumentNullException("node");
            if(string.IsNullOrWhiteSpace(pathAndQuery)) throw new ArgumentNullException("pathAndQuery");

            var parts = pathAndQuery.Split(new char[] { '?' }, 2, StringSplitOptions.None);

            var path = parts[0];
            string query = null;

            if(parts.Length > 1) query = parts[1];

            return node.NavigateToItem(path, query);
        }

        public static DirectoryNode<T, TMetadata> NavigateToDirectory<T, TMetadata>(this DirectoryNode<T, TMetadata> node, string pathAndQuery)
            where T : class
            where TMetadata : IDirectoryNodeMetadata
        {
            if (node == null) throw new ArgumentNullException("node");
            if(string.IsNullOrWhiteSpace(pathAndQuery)) throw new ArgumentNullException("pathAndQuery");

            var parts = pathAndQuery.Split(new char[] { '?' }, 2, StringSplitOptions.None);

            var path = parts[0];
            string query = null;

            if(parts.Length > 1) query = parts[1];

            return node.NavigateToDirectory(path, query);
        }

        private static string GetPath(Uri url)
        {
            if (!url.IsAbsoluteUri) return url.OriginalString;

            return url.AbsolutePath;
        }
    }
}
